/// this file contains a series of type
/// @docs: please see mandoc: `man elf`
/// @docs: please see url link: `https://wiki.osdev.org/ELF`
/// @docs: please see url link pdf: `http://www.skyfree.org/linux/references/ELF_Format.pdf`

package linker

type MachineType = uint8

type MachineTypeStringer struct {
	MachineType
}

// ================== filetype.go
type FileType = uint8

type File struct {
	Name     string
	Contents []byte
	Parent   *File
}

// ================== end filetype.go

// ======================== chunk.go
// interface: Chunker
type Chunker interface {
	GetName() string
	GetShdr() *Shdr
	UpdateShdr(ctx *Context)
	CopyBuf(ctx *Context)
}
type Chunk struct {
	Name  string
	Shdr  Shdr
	Shndx int64
}

// ======================== end chunk.go

// ======================== context.go
type ContextArgs struct {
	Output       string
	Emulation    MachineType
	LibraryPaths []string
}

type Context struct {
	Args ContextArgs
	Buf  []byte

	Ehdr *OutputEhdr
	Shdr *OutputEhdr
	Phdr *OutputEhdr
	Got  *GotSection

	TpAddr uint64

	OutputSections []*OutputSection

	Chunks []Chunker

	Objs      []*ObjectFile
	SymbolMap map[string]*Symbol

	MergedSections []*MergedSection
}

// ======================== end context.go

// ========================= elf.go
type Shdr struct {
	// 32 bits
	Name uint32
	Type uint32
	Link uint32
	Info uint32
	// 64 bits
	Flags     uint64
	Addr      uint64
	Offset    uint64
	Size      uint64
	AddrAlign uint64
	EntSize   uint64
}
type Ehdr struct {
	// 8 bits
	Ident [16]uint8
	// 16 bits
	Type      uint16
	Machine   uint16
	EhSize    uint16
	PhEntSize uint16
	PhNum     uint16
	ShEntSize uint16
	ShNum     uint16
	ShStrndx  uint16
	// 32 bits
	Version uint32
	Flags   uint32
	// 64 bits
	Entry uint64
	PhOff uint64
	ShOff uint64
}
type Phdr struct {
	// 32 bits
	Type  uint32
	Flags uint32
	// 64 bits
	Offset   uint64
	VAddr    uint64
	PAddr    uint64
	FileSize uint64
	MemSize  uint64
	Align    uint64
}
type Sym struct {
	// 8 bits
	Info  uint8
	Other uint8
	// 16 bits
	Shndx uint16
	// 32 bits
	Name uint32
	// 64 bits
	Val  uint64
	Size uint64
}
type Rela struct {
	Offset uint64
	Type   uint32
	Sym    uint32
	Addend int64
}
type ArHdr struct {
	Name [16]byte
	Date []byte
	Uid  [6]byte
	Gid  [6]byte
	Mode [8]byte
	Size [10]byte
	Fmag [2]byte
}

// ========================= end elf.go

type OutputEhdr struct {
	Chunk
}

type OutputPhdr struct {
	Chunk

	Phdrs []Phdr
}

// ========================= inputfile.go
type InputFile struct {
	File         *File
	ElfSections  []Shdr
	ElfSyms      []Sym
	FirstGlobal  int
	ShStrtab     []byte
	SymbolStrtab []byte
	IsAlive      bool
	Symbols      []*Symbol
	LocalSymbols []Symbol
}

// ========================= end inputfile.go

// ========================= outputsection.go
type OutputSection struct {
	Chunk
	Members []*InputSection
	Idx     uint32
}

// ========================= end outputsection.go

// ========================= inputsection.go
type InputSection struct {
	File     *ObjectFile
	Contents []byte
	Shndx    uint32
	ShSize   uint32
	IsAlive  bool
	P2Align  uint8

	Offset        uint32
	OutputSection *OutputSection

	RelsecIdx uint32
	Rels      []Rela
}

// ========================= end inputsection.go

// ========================= objectfile.go
type ObjectFile struct {
	InputFile
	SymtabSec         *Shdr
	SymtabShndxSec    []uint32
	Sections          []*InputSection
	MergeableSections []*MergeableSection
}

// ========================= end objectfile.go

// ========================= symbol.go
type Symbol struct {
	File     *ObjectFile
	Name     string
	Value    uint64
	SymIdx   int
	GotTpIdx int32

	InputSection    *InputSection
	SectionFragment *SectionFragment

	Flags uint32
}

// ========================= end symbol.go
// ========================= gotsection.go
type GotSection struct {
	Chunk
	GotTpSyms []*Symbol
}

type GotEntry struct {
	Idx int64
	Val uint64
}

// ========================= end gotsection.go

// ========================= sectionfragment.go
type SectionFragment struct {
	OutputSection *MergedSection
	Offset        uint32
	P2Align       uint32
	IsAlive       bool
}

// ========================= end sectionfragment.go

// ========================= mergedsection.go
type MergedSection struct {
	Chunk
	Map map[string]*SectionFragment
}
type MergeableSection struct {
	Parent      *MergedSection
	P2Align     uint8
	Strs        []string
	FragOffsets []uint32
	Fragments   []*SectionFragment
}

// ========================= end mergedsection.go
